package main

import "fmt"

func modify1(x int) {
	x = 100
}

func modify2(x *int) {
	*x = 100
}

func pdrStr() *string {
	city := "上海"
	ptr := &city
	return ptr
}

/*
	1. 指针不能运算
	2. go的函数只支持值传递一种方式
		值传递        -> 每次传递都是将实参拷贝一份到形参中, 效率比较低, 但是go存在指针类型解决了该问题
		引用传递      -> 引用实参的内存地址, 效率很高
	3. *a: 表示指针类型的值
	   &a: 表示指针类型的地址
*/

func main() {
	a := 10
	// 指针定义
	b := &a
	fmt.Println(a) // 10
	fmt.Println(b) // 0xc000114000
	// 指针取值
	var c = *b
	fmt.Println(c) // 10

	fmt.Println("res city: ", *pdrStr()) // res city:  上海

	// 指针传值: 值传递和引用传递
	d := 10
	modify1(d)
	fmt.Println(d) // 10
	modify2(&d)
	fmt.Println(d) // 100

	// new：如果使用了new之后，编译器会提前根据数据的类型申明一个内存空间，这里的默认值为0
	var a1 *int // 申明了一个变量，但是变量没有初始值，没有内存
	/**区别于`var a1 int`这种写法
	1、像int(int8 int16...) byte float string rune bool等都有默认值，所以可以直接赋值
	2、像：指针、切片、map、接口这些类型的默认为nil
	*/
	a1 = new(int)
	*a1 = 10
	fmt.Println(*a1) // 10

	// make：提前根据数据的类型申明一个内存空间(更加常用，一般用于map和切片)
	var b1 map[string]int = make(map[string]int, 10)
	b1["沙河娜扎"] = 100
	fmt.Println(b1) // map[沙河娜扎:100]

	/**
	1、new函数返回的是这个值的指针
	2、make函数返回的是指定类型的实例对象
	*/
}
